#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <signal.h>

#include <sitetypes.h>
#include <proto.h>

#include "mainconf.h"

#include "conf.h"

#define CMDMAX	8192
#define IPLENMAX	65535

struct config_st configure;

static int get_rcvsocket(void)
{
	int sd;
	struct ip_mreqn mreq;

	sd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sd<0) {
		perror("socket()");
		return -1;
	}

	inet_pton(AF_INET, configure.mgroup, &mreq.imr_multiaddr);
	inet_pton(AF_INET, "0.0.0.0", &mreq.imr_address);
	mreq.imr_ifindex = if_nametoindex(configure.ifname);
	if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))<0) {
		perror("setsockopt()");
		close(sd);
		return -1;
	}

	if (bind(sd, (void*)&configure.rcv_addr, sizeof(configure.rcv_addr))<0) {
		perror("bind()");
		close(sd);
		return -1;
	}
}

/*
 * 	-P	:指定播放器命令行
 *	-p	:指定接收端口
 *	-m	:指定多波组
 */
int
main()
{
	int pd[2], sd;
	static char command[CMDMAX];
	struct msg_st *rbufp;
	struct sockaddr_in server_addr;
	socklen_t server_addr_len;
	chnid_t chosen_id;
	ssize_t pos, len, ret;
	pid_t pid;

	signal(SIGPIPE, SIG_IGN);

	rbufp = malloc(IPLENMAX);
	if (rbufp==NULL) {
		perror("alloca()");
		exit(1);
	}

	/* Set default configure */
	configure.player_cmd = DEFAULT_PLAYER_CMD;
	configure.player_arg = DEFAULT_PLAYER_ARG;
	configure.rcv_addr.sin_family = AF_INET;
	configure.rcv_addr.sin_port = htons(atoi(DEFAULT_RCVPORT));
	inet_pton(AF_INET, "0.0.0.0", &configure.rcv_addr.sin_addr);
	configure.ifname = "eth0";
	configure.mgroup = DEFAULT_MGROUP;
	/* 解析配置文件（如果有的话），修正configure */
	/* 解析环境变量（如果有的话），修正configure */
	/* 解析命令行参数，修正configure */

	if (pipe(pd)<0) {
		perror("pipe()");
		exit(1);
	}

	pid = fork();
	if (pid<0) {
		perror("fork()");
		exit(1);
	}
	if (pid==0) {
		close(pd[1]);
		dup2(pd[0], 0);
		if (pd[0]!=0) {
			close(pd[0]);
		}
		strncpy(command, configure.player_cmd, CMDMAX);
		strncat(command, " ", CMDMAX);
		strncat(command, configure.player_arg, CMDMAX);
		execl("/bin/sh", "sh", "-c", command, NULL);
		fprintf(stderr, "execl(%s): %m\n", command);
		exit(1);
	}

	close(pd[0]);

	sd = get_rcvsocket();

	assert(sd>=0);

	server_addr_len = sizeof(server_addr);
	while (1) {
		while (recvfrom(sd, rbufp, IPLENMAX, 0, (void*)&server_addr, &server_addr_len)<=0) {
			if (errno!=EINTR) {
				perror("recvfrom()");
				exit(1);
			}
		}
		if (rbufp->chnid==CHNID_LIST) {
			break;
		} 
	}

	/* 选频道 (暂假选)*/
	chosen_id = 1;


	while (1) {
		while ((len=recvfrom(sd, rbufp, IPLENMAX, 0, (void*)&server_addr, &server_addr_len))<=0) {
			if (errno!=EINTR) {
				perror("recvfrom()");
				exit(1);
			}
		}
		if (rbufp->chnid==chosen_id) {
			len -= sizeof(char);
			pos = 0;
			while (len>0) {
				ret = write(pd[1], rbufp+pos, len);
				if (ret<0) {
					perror("write()");
					exit(1);
				}
				len -= ret;
				pos	+= ret;
			}
		} 
	}

	close(sd);

	return 0;
}

